using AutoMapper;
using MediatR;
using SqlSugar;
using TaskProject.Application.Command.Plan;
using TaskProject.Domain.Plan;
using TaskProject.ErrorCode;
using TaskProject.InfrasIntructure.Implement;
using TaskProject.Extension;

namespace TaskProject.Application.Handler.Plan
{
    /// <summary>
    /// 生产计划操作处理器
    /// </summary>
    public class ProductionPlanOperationHandler : IRequestHandler<ProductionPlanOperationCommand, APIResult<bool>>
    {
        private readonly DatabaseContext _db;
        private readonly IMapper _mapper;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public ProductionPlanOperationHandler(DatabaseContext db, IMapper mapper, IHttpContextAccessor httpContextAccessor)
        {
            _db = db;
            _mapper = mapper;
            _httpContextAccessor = httpContextAccessor;
        }

        public async Task<APIResult<bool>> Handle(ProductionPlanOperationCommand request, CancellationToken cancellationToken)
        {
            var result = new APIResult<bool>();

            try
            {
                // 检查生产计划是否存在
                var productionPlan = await _db.sqlSugar.Queryable<ProductionPlanModel>()
                    .Where(p => p.PlanId == request.PlanId && !p.IsDel)
                    .FirstAsync(cancellationToken);

                if (productionPlan == null)
                {
                    result.Code = APIEnum.Fail;
                    result.Msg = "生产计划不存在";
                    return result;
                }

                // 验证操作类型和状态转换的合法性
                if (!IsValidOperation(productionPlan.PlanStatus, request.OperationType))
                {
                    result.Code = APIEnum.Fail;
                    result.Msg = GetInvalidOperationMessage(productionPlan.PlanStatus, request.OperationType);
                    return result;
                }

                // 获取操作后的状态
                var newStatus = GetNewStatus(request.OperationType);
                var operationTypeName = GetOperationTypeName(request.OperationType);

                // 开始事务
                var resultFlag = await _db.sqlSugar.Ado.UseTranAsync(async () =>
                {
                    // 更新生产计划状态
                    await _db.sqlSugar.Updateable<ProductionPlanModel>()
                        .SetColumns(p => new ProductionPlanModel
                        {
                            PlanStatus = newStatus,
                            UpdateName = "系统用户", // 可以从当前登录用户获取
                            UpdateDate = DateTime.Now
                        })
                        .Where(p => p.PlanId == request.PlanId)
                        .ExecuteCommandAsync(cancellationToken);

                    // 记录操作日志
                    var operationLog = new ProductionPlanOperationLogModel
                    {
                        LogId = await GetNextLogIdAsync(),
                        PlanId = request.PlanId,
                        OperationType = request.OperationType,
                        OperationTypeName = operationTypeName,
                        OperationDescription = request.OperationDescription ?? $"{operationTypeName}生产计划",
                        BeforeStatus = productionPlan.PlanStatus,
                        AfterStatus = newStatus,
                        OperatorName = "系统用户", // 可以从当前登录用户获取
                        OperationTime = DateTime.Now,
                        IpAddress = _httpContextAccessor.HttpContext?.GetClientIpAddress() ?? "127.0.0.1",
                        Remarks = request.Remarks
                    };

                    await _db.sqlSugar.Insertable(operationLog).ExecuteCommandAsync(cancellationToken);

                    return true;
                });

                if (resultFlag.IsSuccess)
                {
                    result.Code = APIEnum.Success;
                    result.Msg = $"{operationTypeName}操作成功";
                    result.Data = resultFlag.Data;
                }
                else
                {
                    result.Code = APIEnum.Fail;
                    result.Msg = $"操作失败：{resultFlag.ErrorMessage}";
                }
            }
            catch (Exception ex)
            {
                result.Code = APIEnum.Fail;
                result.Msg = $"操作失败：{ex.Message}";
            }

            return result;
        }

        /// <summary>
        /// 验证操作是否合法
        /// </summary>
        private bool IsValidOperation(int currentStatus, int operationType)
        {
            return operationType switch
            {
                3 => currentStatus == 1, // 启动：只能从已确认状态启动
                4 => currentStatus == 2, // 暂停：只能从执行中状态暂停
                5 => currentStatus == 4, // 恢复：只能从暂停状态恢复
                6 => currentStatus == 2, // 完成：只能从执行中状态完成
                7 => currentStatus is 0 or 1 or 2, // 取消：可以从草稿、已确认、执行中状态取消
                _ => false
            };
        }

        /// <summary>
        /// 获取无效操作的错误消息
        /// </summary>
        private string GetInvalidOperationMessage(int currentStatus, int operationType)
        {
            var statusName = GetPlanStatusName(currentStatus);
            var operationName = GetOperationTypeName(operationType);

            return $"当前状态为\"{statusName}\"，不能执行\"{operationName}\"操作";
        }

        /// <summary>
        /// 获取操作后的新状态
        /// </summary>
        private int GetNewStatus(int operationType)
        {
            return operationType switch
            {
                3 => 2, // 启动 -> 执行中
                4 => 4, // 暂停 -> 暂停
                5 => 2, // 恢复 -> 执行中
                6 => 3, // 完成 -> 已完成
                7 => 4, // 取消 -> 已取消
                _ => 0
            };
        }

        /// <summary>
        /// 获取操作类型名称
        /// </summary>
        private string GetOperationTypeName(int operationType)
        {
            return operationType switch
            {
                3 => "启动",
                4 => "暂停",
                5 => "恢复",
                6 => "完成",
                7 => "取消",
                _ => "未知操作"
            };
        }

        /// <summary>
        /// 获取计划状态名称
        /// </summary>
        private string GetPlanStatusName(int status)
        {
            return status switch
            {
                0 => "草稿",
                1 => "已确认",
                2 => "执行中",
                3 => "已完成",
                4 => "已取消",
                _ => "未知状态"
            };
        }

        /// <summary>
        /// 获取下一个日志ID
        /// </summary>
        private async Task<int> GetNextLogIdAsync()
        {
            var maxId = await _db.sqlSugar.Queryable<ProductionPlanOperationLogModel>().MaxAsync(p => (int?)p.LogId) ?? 0;
            return maxId + 1;
        }
    }
} 